/*
 * axiFpga.c 
 */

/* includes */

#include <vxWorks.h>
#include <vsbConfig.h>
#include <intLib.h>
#include <errnoLib.h>
#include <errno.h>
#include <sioLib.h>
#include <ioLib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vxAtomicLib.h>
#include <semLib.h>
#include <sysLib.h>
#include <vmLib.h>
#include <stdio.h>
#include <hwif/vxBus.h>
#include <hwif/buslib/vxbFdtLib.h>
#include <taskLib.h>
#include "axiFpga.h"
 

#include <semLib.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <logLib.h>
#include <lstLib.h>
#include <iosLib.h>
#include <subsys/timer/vxbTimerLib.h>
#include <hwif/buslib/vxbFdtLib.h>
static STATUS axiFpgaInited = ERROR;

/* VxBus methods */
LOCAL STATUS axiFpgaProbe  (VXB_DEV_ID);
LOCAL STATUS axiFpgaAttach (VXB_DEV_ID);
LOCAL STATUS axiFpgaInit(VXB_DEV_ID pDev);

LOCAL VXB_DRV_METHOD axiFpgaMethods[] =
   {
   { VXB_DEVMETHOD_CALL(vxbDevProbe),  axiFpgaProbe},
   { VXB_DEVMETHOD_CALL(vxbDevAttach), axiFpgaAttach},
   VXB_DEVMETHOD_END
   };

VXB_DRV  axiFpgaDrv =
    {
    { NULL } ,
	AXI_FPGA_NAME,                    /* drvName */
    "AXI FPGA driver",  /* Description */
    VXB_BUSID_FDT,                  /* Class */
    0,                              /* Flags */
    0,                              /* Reference count */
	axiFpgaMethods                 /* Method table */
    };
/* match table */
LOCAL VXB_FDT_DEV_MATCH_ENTRY axiFpgaMatch[] =
    {
        { "dd,axiFpga",   (void *) NULL },
        {} /* Empty terminated list */
    };

UINT32 			groupState;
/**
* axiFpgaOpen
* @brief 	IFC FPGA设备打开函数，实现驱动注册，分配资源，实现初始化；返回设备句柄
* @param	ppDev	存放设备句柄指针
* @param	unit	设备单元号
* @return	OK		打开成功
* @return   ERROR   打开失败，设备已打开或者不存在
* 
*/

void axiFpgaOpen(VXB_DEV_ID * ppDev, UINT32 unit)
{
	if(axiFpgaInited == ERROR)
		axiFpgaInited = vxbDrvAdd(&axiFpgaDrv);
	
	if(axiFpgaInited == OK)
		*ppDev  = vxbDevAcquireByName(AXI_FPGA_NAME, unit);	
}

/**
* axiFpgaClose
* @brief IFC FPGA 设备关闭函数
*/
int axiFpgaClose(VXB_DEV_ID pDev)
{
	return OK;
} 
 


/*********************************************************************
*
* axiFpgaProbe - check whether device and driver go together
*
* This routine probe a device with a device driver.
*
* RETURNS: OK if the device and driver match up, ERROR otherwise
*
* ERRNO
*/

LOCAL STATUS axiFpgaProbe
(
	VXB_DEV_ID pDev
)
{
	return vxbFdtDevMatch (pDev, axiFpgaMatch, NULL);
}


int cntirq = 0 ;
LOCAL STATUS axiFpgaHandler 
(
	VXB_DEV_ID pDev
)
{
	int i;
	cntirq++; 
	UINT32 intStatus = ddRegGet(FPGA_INT_STATUS_REG);
	ddRegSet(FPGA_INT_STATUS_REG, intStatus); 
	// 遍历每一位，判断哪一位被置位
    for (i = 0; i < 20; i++) {
        if (intStatus & (1U << i)) {
        	groupState |= (1U << i);
        }
    }

    


    return OK;
}

 
  
/*******************************************************************************
*
* axiFpgaAttach - attach fpga device
*
* This routine attach qixis device with vxbQixisDrv,it creats device
* and assign resource for it.
*
* \NOMANUAL
*
* RETURNS: OK if attached successfully, otherwise ERROR
*
* ERRNO: N/A
*/
LOCAL STATUS axiFpgaAttach(VXB_DEV_ID pDev) {
    FPGA_DRV_CTRL *pDrvCtrl;
    VXB_RESOURCE_ADR * pResAdr = NULL;
    VXB_RESOURCE * pRes;
    VXB_FDT_DEV *pFdtDev = NULL;
    PHYS_ADDR    physicalAddr;
    char *pname = NULL;
    int proplen = 0;
    VXB_DEV_ID   pParDev;
    
    /*查找父节点*/
     if ((pParDev = vxbDevParent (pDev)) == NULL){
    	 printf("vxbFdtDevGet failed 0x%08x\n ",pParDev);
         return (ERROR);
     }
    /* 分配驱动控制结构 */
    pDrvCtrl = vxbMemAlloc(sizeof(FPGA_DRV_CTRL));
    if(pDrvCtrl == NULL) 
		return ERROR;
    bzero((char *)pDrvCtrl, sizeof(FPGA_DRV_CTRL));
    vxbDevSoftcSet(pDev, pDrvCtrl);
    pDrvCtrl->pDev = pDev;
    groupState = 0;
    

    
    /**为FPGA分配资源**/
    pRes = vxbResourceAlloc(pDev, VXB_RES_MEMORY, 0);
    if(pRes == NULL)
    	goto Exit;

    
    pResAdr = (VXB_RESOURCE_ADR *)pRes->pRes;
    if (pResAdr == NULL)
		goto Exit;


    /*获取虚拟映射空间*/
    pDrvCtrl->fpgaBar = (void *)pResAdr->virtual;
    if(vmTranslate (NULL,(VIRT_ADDR) pDrvCtrl->fpgaBar, &physicalAddr) == ERROR)
    	{
        free (pDrvCtrl->fpgaBar);
        return (ERROR);	
    	}
    printf("Fpag PHY is 0x%llx virAddr 0x%08x  PhyAddr 0x%x%08x \n",pResAdr->start,pDrvCtrl->fpgaBar,HIGH32(physicalAddr),LOW32(physicalAddr));

    pDrvCtrl->fpgaPhyBar = physicalAddr;
    
    pDrvCtrl->fpgaHandle = pResAdr->pHandle;
    
    
    /* 创建信号量 */
     pDrvCtrl->fpgaSem = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); 

     //对中断寄存器进行初始化

     axiFpgaSet(pDev, FPGA_RESET_REG, FPGA_RESET_VALUE);
     axiFpgaSet(pDev, FPGA_OUTPUT_LEVEL_REG,FPGA_OUT_LOW_IDLE);
     axiFpgaSet(pDev, FPGA_INT_TYPE_REG, FPGA_INT_TYPE_LEVEL);
     axiFpgaSet(pDev, FPGA_INT_POLARITY_REG, FPGA_INT_POL_RISING);
     axiFpgaSet(pDev, FPGA_GLOBAL_ENABLE_REG, FPGA_GLOBAL_INT_ENABLE);
     axiFpgaSet(pDev, FPGA_INT_ENABLE_REG, 0xffffffff); 
    /* 获取中断资源 */

	pDrvCtrl->intRes = vxbResourceAlloc(pDev, VXB_RES_IRQ, 0);
	if(pDrvCtrl->intRes == NULL )
	{
	  logMsg("Failed to vxbResourceAlloc interrupt of device %s\n", (int)AXI_FPGA_NAME, 0, 0, 0, 0, 0);
		goto Exit;
	}
	(void) vxbIntConnect (pDev, pDrvCtrl->intRes, (VOIDFUNCPTR) axiFpgaHandler, pDev);
	(void) vxbIntEnable (pDev, pDrvCtrl->intRes);

    return OK;

Exit:
    if(pDrvCtrl != NULL) {
        free(pDrvCtrl);
    }
    return ERROR;
}


/**
* @brief	FPGA 寄存器读取函数
* @param[in]	pDev   设备句柄
* @param[in]	offset 寄存器偏移地址
* @return	特定寄存器地址下寄存器值
*/
UINT32 axiFpgaGet(VXB_DEV_ID pDev, UINT32 offset)
{
	 
	UINT32 val;
	val = CSR_READ_4(pDev, offset);        

	return val;
	
	
}



/**
* axiFpgaSet
* @brief	FPGA寄存器设置函数
* @param[in]	pDev   设备句柄
* @param[in]	offset 寄存器偏移地址
* @param[in]	val    寄存器值
* @return	返回值：无
*/
void axiFpgaSet(VXB_DEV_ID pDev, UINT32 offset, UINT32 val)
{
 
	CSR_WRITE_4(pDev, offset, val);
}


/*##########################################杂散函数##########################################*/
/**
 * ddRegGet
 * @brief 	寄存器获取函数
 * @param[in]	offset    寄存器偏移地址
 * @return	返回值：寄存器值
 */
UINT32 ddRegGet(UINT32 offset)
{
	VXB_DEV_ID pDev;
	UINT32 value; 
	axiFpgaOpen(&pDev,0);
	value = axiFpgaGet(pDev, offset); 	
	return(value);	
}
/**
 * ddRegSet
 * @brief 	寄存器设置函数 
 * @param[in]	offset    寄存器偏移地址
 * @param[in]	val    	 寄存器值
 */
void ddRegSet(UINT32 offset, UINT32 val)
{
	VXB_DEV_ID pDev;
	axiFpgaOpen(&pDev,0);
	axiFpgaSet(pDev, offset, val); 	
 }
 
/*******************************************************************************
*
* parseTimeRegister - 解析时间寄存器值
*
* 从32位时间寄存器值中解析出时、分、秒
*
* RETURNS: 解析后的时间结构体
*/
void parseTimeRegister(UINT32 timeReg, TIME_DATE *pTimeDate)
{
    /* 根据位域解析时间 */
    pTimeDate->second = (timeReg >> 0) & 0xFF;   /* 位[7:0] = 秒 */
    pTimeDate->minute = (timeReg >> 8) & 0xFF;   /* 位[15:8] = 分 */
    pTimeDate->hour   = (timeReg >> 16) & 0xFF;  /* 位[23:16] = 时 */
}
 

/*******************************************************************************
*
* parseDateRegister - 解析日期寄存器值
*
* 从32位日期寄存器值中解析出年、月、日
*
* RETURNS: 解析后的日期结构体
*/
void parseDateRegister(UINT32 dateReg, TIME_DATE *pTimeDate)
{
    /* 根据位域解析日期 */
    pTimeDate->day   = (dateReg >> 0) & 0xFF;     /* 位[7:0] = 日 */
    pTimeDate->month = (dateReg >> 8) & 0xFF;     /* 位[15:8] = 月 */
    pTimeDate->year  = (dateReg >> 16) & 0xFFFF;  /* 位[31:16] = 年 */
}

STATUS timeDateGet(TIME_DATE *pTimeDate)
{
    UINT32 timeReg, dateReg;
     
    
    /* 读取时间寄存器 */
    timeReg = ddRegGet(AXILITE2AXIS_LOGIC_TIME);
    
    /* 读取日期寄存器 */
    dateReg = ddRegGet(AXILITE2AXIS_LOGIC_DATE);
    
    /* 解析时间 */
    parseTimeRegister(timeReg, pTimeDate);
    
    /* 解析日期 */
    parseDateRegister(dateReg, pTimeDate);
    
    return OK;
}

/*******************************************************************************
*
* timeDateShow - 显示当前时间和日期
*
* 以可读格式打印当前时间和日期
*
* RETURNS: OK如果成功，否则ERROR
*/
STATUS timeDateShow(void)
{
    TIME_DATE timeDate;
    STATUS status;
    
    status = timeDateGet(&timeDate);
    if (status != OK) {
        return status;
    }
    
    /* 打印时间和日期 */
    printf("PL Logic Version Date: %04d-%02d-%02d\n", timeDate.year, timeDate.month, timeDate.day);
    printf("PL Logic Version Time: %02d:%02d:%02d\n", timeDate.hour, timeDate.minute, timeDate.second);
    
    return OK;
}

// 获取FPGA所在的槽位号（假设通过特定寄存器读取）
// 注意：需根据实际硬件调整AXILITE2AXIS_BASE和偏移量
unsigned int get_fpga_slot_number() {
    // 示例：槽位号存储在基地址+0x08偏移的32位寄存器中
     return ddRegGet(0x8) & 0xFF;  
}

// 示例测试函数（可选，用于验证功能）
void test_slot_number() {
    unsigned int slot = get_fpga_slot_number();
    printf("当前FPGA所在槽位号: %d\n", slot);
}

/**
 * @brief 同步控制所有采集组的开启或关闭
 * 
 * 此函数通过操作寄存器 0x10 来同步控制所有 20 组采集的开启或关闭。
 * 该寄存器每一位对应一组采集，置 1 使能，置 0 关闭。
 * 
 * @param enable 控制标志，1 表示开启所有组采集，0 表示关闭所有组采集
 */
 void syncControlAllGroups(unsigned char enable) {
    unsigned int val = enable ? 0xFFFFF : 0x0; // 0xFFFFF 的低 20 位全为 1
    ddRegSet(0x10, val);
}
/**
 * @brief 启用或禁用指定的采集组
 * 
 * 此函数通过操作指定采集组的控制寄存器，根据传入的 enable 参数
 * 来决定是启用还是禁用该采集组。
 * 
 * @param group 要操作的采集组编号
 * @param enable 控制标志，1 表示启用采集组，0 表示禁用采集组
 */
void enable_group(unsigned char group, unsigned char enable) {
	
    unsigned int ctrl_reg = HEIR_SAM_CTRL_REG(group);
    unsigned int val = ddRegGet(ctrl_reg);
     val = enable ? (val | CTRL_EN) : (val & ~CTRL_EN);
     
     if(enable)
    	    groupState = groupState & (~(1<<group));

    ddRegSet(ctrl_reg, val);
}
/**
 * @brief 查询指定采集组是否使能
 * 
 * 此函数通过将指定采集组的 ctrl_reg 的 CTRL_EN 位与 0x10 寄存器的某一位相与，
 * 判断该采集组是否使能。结果为 1 表示使能，0 表示关闭。
 * 
 * @param group 要查询的采集组编号
 * @return unsigned char 该采集组的使能状态，1 表示使能，0 表示关闭
 */
unsigned char is_group_enabled(unsigned char group) {
    unsigned int ctrl_reg = HEIR_SAM_CTRL_REG(group);
    unsigned int ctrl_val = ddRegGet(ctrl_reg);
    unsigned int group_mask = 1U << group;
    unsigned int reg_0x10_val = ddRegGet(0x10);
    
    unsigned char ctrl_en = (ctrl_val & CTRL_EN) ? 1 : 0;
    unsigned char reg_0x10_bit = (reg_0x10_val & group_mask) ? 1 : 0;
    
    return ctrl_en & reg_0x10_bit;
}

/**
 * @brief 查询指定采集组是否完成采集
 * 
 * 此函数用于查询指定采集组是否完成采集，具体实现需根据硬件逻辑完善。
 * 
 * @param group 要查询的采集组编号
 * @return unsigned char 采集完成状态，1 表示完成，0 表示未完成
 */
unsigned char is_group_finish(unsigned char group) {
    unsigned int status = groupState & (1U << group);
    unsigned char result = status ? 1 : 0;
    
    return result;
}

/**
 * @brief 清除groupState的函数
 * 
 * 此函数用于清除所有采集组的完成状态，将groupState重置为0。
 * 可以选择清除所有组状态或清除指定组的状态。
 * 
 * @param group 要清除的采集组编号，如果为0xFF则清除所有组状态
 */
void clear_group_state(unsigned char group) {
    if (group == 0xFF) {
        // 清除所有组状态
        groupState = 0;
    } else {
        // 清除指定组的状态
        groupState &= ~(1U << group);
    }
}

/**
 * @brief 设置指定采集组的采样时长
 * 
 * 此函数用于设置指定采集组的采样时长，将输入的时间（单位：秒）乘以采样率
 * 后写入对应的 0x04 偏移寄存器。
 * 
 * @param group 要设置采样时长的采集组编号
 * @param sample_duration 采 
 */
void set_sample_duration(unsigned char group, unsigned int sample_duration) {
     unsigned int sample_duration_reg = HEIR_SAM_CTRL_REG(group) + 0x04;
    ddRegSet(sample_duration_reg, sample_duration);
}

/**
 * @brief 选择指定采集组的数据来源
 * 
 * 此函数用于选择指定采集组的数据来源，通过控制 ctrl_reg 的 bit3 实现。
 * 设置为 1 代表采集测试数据，设置为 0 代表采集外部信号。
 * 
 * @param group 要设置数据来源的采集组编号
 * @param use_test_data 数据来源标志，1 表示采集测试数据，0 表示采集外部信号
 */
void select_data_source(unsigned char group, unsigned char use_test_data) {
    unsigned int ctrl_reg = HEIR_SAM_CTRL_REG(group);
    unsigned int val = ddRegGet(ctrl_reg);
    
    if (use_test_data) {
        val |= (1 << 3);  // 设置 bit3 为 1
    } else {
        val &= ~(1 << 3); // 设置 bit3 为 0
    }
    
    ddRegSet(ctrl_reg, val);
}

/**
 * @brief 配置指定采集组的边沿触发参数
 * 
 * 此函数用于配置指定采集组的边沿触发功能，包括使能边沿触发、设置触发边沿类型和触发引脚。
 * 
 * @param group 要配置的采集组编号
 * @param edge_pin 触发边沿的引脚编号
 * @param enable 边沿采集使能标志，1 表示使能，0 表示关闭
 * @param rise_fall 触发边沿类型，1 表示上升沿触发，0 表示下降沿触发
 */ 
 void config_edge_trigger(unsigned char group, unsigned char edge_pin, unsigned char enable, unsigned char rise_fall) {
    unsigned int ctrl_reg = HEIR_SAM_CTRL_REG(group);
    unsigned int val = ddRegGet(ctrl_reg);
    
    if (enable) {
        val |= CTRL_EDGE_EN;  // 使能边沿触发
        val &= ~CTRL_EDGE_RISE;  // 清除原有沿类型
        val |= (rise_fall ? CTRL_EDGE_RISE : 0);
        val = (val & ~0xF0) | CTRL_EDGE_PIN(edge_pin);
    } else {
        val &= ~CTRL_EDGE_EN;  // 关闭边沿触发
    }
    
    ddRegSet(ctrl_reg, val);
    logMsg("config_edge_trigger:ctrl_reg 0x%x\n",val,2,3,4,5,6);
}
/**
 * @brief 配置指定采集组的自测试功能
 * 
 * 此函数用于配置指定采集组的自测试功能，通过控制 ctrl_reg 的 CTRL_SELF_TEST 位实现。
 * 设置为 1 代表启用自测试，设置为 0 代表禁用自测试。
 * 
 * @param group 要配置自测试功能的采集组编号
 * @param enable 自测试使能标志，1 表示启用，0 表示禁用
 */
void config_self_test(unsigned char group, unsigned char enable) {
    unsigned int ctrl_reg = HEIR_SAM_CTRL_REG(group);
    unsigned int val = ddRegGet(ctrl_reg);
    
    if (enable) {
        val |= CTRL_SELF_TEST;  // 设置 CTRL_SELF_TEST 位为 1
    } else {
        val &= ~CTRL_SELF_TEST; // 设置 CTRL_SELF_TEST 位为 0
    }
    
    ddRegSet(ctrl_reg, val);
}
/**
 * @brief 配置指定采集组的采样持续时间寄存器
 * 
 * 此函数用于设置指定采集组的 HEIR_SAM_SAMPLE_DUR 寄存器值。
 * 
 * @param group 要配置的采集组编号
 * @param duration 要设置的采样持续时间值
 */
void config_sample_dur(unsigned char group, unsigned int duration) {
    unsigned int sample_dur_reg = HEIR_SAM_SAMPLE_DUR(group);
    ddRegSet(sample_dur_reg, duration);
}

/**
 * @brief 设置指定采集组的缓冲区地址
 * 
 * 此函数用于设置指定采集组的缓冲区地址，该寄存器偏移为 0x08。
 * 
 * @param group 要设置缓冲区地址的采集组编号
 * @param buffer_addr 要设置的缓冲区地址
 */
void set_buffer_address(unsigned char group, unsigned int buffer_addr) {
    unsigned int buffer_addr_reg = HEIR_SAM_CTRL_REG(group) + 0x08;
    ddRegSet(buffer_addr_reg, buffer_addr);
}
 
/**
 * @brief 读取指定采集组的采集完成次数
 * 
 * 此函数通过读取对应的寄存器，获取指定采集组的采集完成次数。
 * 
 * @param group 要读取的采集组编号
 * @return unsigned int 指定采集组的采集完成次数
 */
unsigned int get_complete_count(unsigned char group) {
    return ddRegGet(HEIR_SAM_COMPLETE_CNT(group));
}

/**
 * @brief 读取指定采集组的当前数据长度
 * 
 * 此函数通过读取对应的寄存器，获取指定采集组当前采集数据的长度，单位为字节。
 * 
 * @param group 要读取的采集组编号
 * @return unsigned int 指定采集组的当前数据长度，单位为字节
 */
unsigned int get_data_length(unsigned char group) {
    return ddRegGet(HEIR_SAM_LENGTH(group));
}

/**
 * @brief 清除指定采集组的中断标志
 * 
 * 此函数通过向中断标志寄存器写入对应的值，清除指定采集组的中断标志。
 * 
 * @param group 要清除中断标志的采集组编号
 */
void clear_interrupt(unsigned char group) {
    ddRegSet(FPGA_INT_STATUS_REG, FPGA_INT_BIT(group));
}
/**
 * @brief 打印中断状态寄存器的值
 * 
 * 此函数通过调用 ddRegGet 函数读取中断状态寄存器的值，
 * 并将其以十六进制格式打印输出。
 */
 void printInterruptStatus(void) {
    UINT32 intStatus = ddRegGet(FPGA_INT_STATUS_REG);
    printf("Interrupt status register value: 0x%x\n", intStatus);
}
/**
 * @brief 清除指定采集组的中断标志
 * 
 * 此函数通过向中断标志寄存器写入对应的值，清除指定采集组的中断标志。
 * 
 * @param group 要清除中断标志的采集组编号
 */
void enable_interrupt(unsigned char group) {
    ddRegSet(FPGA_INT_ENABLE_REG, FPGA_INT_BIT(group));
}

 

/**
 * @brief 打印指定采集组的寄存器信息
 * 
 * 此函数会读取指定采集组的控制寄存器、采样时长、数据存储地址、
 * 采集完成次数、采集长度和缓存溢出次数，并将这些信息打印出来。
 * 
 * @param group 要打印信息的采集组编号
 */
 void print_group_info(unsigned char group) {
    // 计算各寄存器偏移地址
    unsigned int ctrl_reg = HEIR_SAM_CTRL_REG(group);
    unsigned int sample_duration_reg = ctrl_reg + 0x04;
    unsigned int buffer_addr_reg = ctrl_reg + 0x08;
    unsigned int complete_count_reg = ctrl_reg + 0x10;
    unsigned int data_length_reg = ctrl_reg + 0x14;
    unsigned int overflow_count_reg = ctrl_reg + 0x18;

    // 读取各寄存器值
    unsigned int ctrl_val = ddRegGet(ctrl_reg);
    unsigned int sample_duration = ddRegGet(sample_duration_reg);
    unsigned int buffer_addr = ddRegGet(buffer_addr_reg);
    unsigned int complete_count = ddRegGet(complete_count_reg);
    unsigned int data_length = ddRegGet(data_length_reg);
    unsigned int overflow_count = ddRegGet(overflow_count_reg);

    // 解析控制寄存器
    unsigned char acquire_enable = (ctrl_val >> 0) & 0x01;
    unsigned char edge_enable = (ctrl_val >> 1) & 0x01;
    unsigned char edge_type = (ctrl_val >> 2) & 0x01;
    unsigned char edge_pin = (ctrl_val >> 4) & 0x0F;

    // 打印信息
    printf("Group %d 寄存器信息:\n", group);
    printf("ctrl_reg  0x%x\n", ctrl_val);
    printf("  采集使能: %s\n", acquire_enable ? "使能" : "关闭");
    printf("  边沿使能: %s\n", edge_enable ? "使能" : "关闭");
    printf("  edge type: %s\n", edge_type ? "rising edge" : "falling edge");
    printf("  edge pin %d\n", edge_pin);
    printf("采样时长(0x%02x): 0x%08x\n", sample_duration_reg, sample_duration);
    printf("数据存储地址(0x%02x): 0x%08x\n", buffer_addr_reg, buffer_addr);
    printf("采集完成次数(0x%02x): %u\n", complete_count_reg, complete_count);
    printf("sample length(0x%02x): %d \n", data_length_reg, data_length*8);
    printf("缓存溢出次数(0x%02x): %u\n", overflow_count_reg, overflow_count);   
    printf("\n");
}
 
